package com.example.utility.aes;

import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.security.SecureRandom;
import java.util.Base64;

public class AESCBCUtil {

    private static final String ALGORITHM = "AES";
    private static final String TRANSFORMATION = "AES/CBC/PKCS5Padding";

    /**
     * 使用 CBC 模式加密
     */
    public static String encrypt(String plainText, String keyString) throws Exception {
        // 创建密钥
        SecretKeySpec secretKey = new SecretKeySpec(keyString.getBytes(), ALGORITHM);

        // 生成随机 IV
        byte[] iv = new byte[16];
        new SecureRandom().nextBytes(iv);
        IvParameterSpec ivSpec = new IvParameterSpec(iv);

        // 加密
        Cipher cipher = Cipher.getInstance(TRANSFORMATION);
        cipher.init(Cipher.ENCRYPT_MODE, secretKey, ivSpec);
        byte[] encryptedData = cipher.doFinal(plainText.getBytes());

        // 将 IV 和加密数据组合
        byte[] encryptedBytes = new byte[iv.length + encryptedData.length];
        System.arraycopy(iv, 0, encryptedBytes, 0, iv.length);
        System.arraycopy(encryptedData, 0, encryptedBytes, iv.length, encryptedData.length);

        return Base64.getEncoder().encodeToString(encryptedBytes);
    }

    /**
     * 使用 CBC 模式解密
     */
    public static String decrypt(String encryptedText, String keyString) throws Exception {
        // 创建密钥
        SecretKeySpec secretKey = new SecretKeySpec(keyString.getBytes(), ALGORITHM);

        // 解码加密数据
        byte[] encryptedBytes = Base64.getDecoder().decode(encryptedText);

        // 提取 IV
        byte[] iv = new byte[16];
        System.arraycopy(encryptedBytes, 0, iv, 0, iv.length);
        IvParameterSpec ivSpec = new IvParameterSpec(iv);

        // 提取实际加密数据
        byte[] encryptedData = new byte[encryptedBytes.length - 16];
        System.arraycopy(encryptedBytes, 16, encryptedData, 0, encryptedData.length);

        // 解密
        Cipher cipher = Cipher.getInstance(TRANSFORMATION);
        cipher.init(Cipher.DECRYPT_MODE, secretKey, ivSpec);
        byte[] decryptedBytes = cipher.doFinal(encryptedData);

        return new String(decryptedBytes);
    }
}

